
<!-- ele-ui -->
<template>
  <div>
    <div class="wrapper">
      <div class="left">
        <draggable v-model="arr1" :options="{ group: { name: 'itxst', pull: 'clone', put: false, }, sort: false }"
          animation="300" :move="onMove">
          <transition-group class="left-group">
            <div class="item flex-item" v-for="item in arr1" :key="item.id" @mouseenter="mouseEnter(item)">
              <div class="flex-item-item">
                <label class="move">{{ item.name }}</label><a-icon :type="item.icon" />
              </div>
            </div>
          </transition-group>
        </draggable>
      </div>
      <div class="center">
        <div class="left right">
          <draggable v-model="arr2" group="itxst" animation="300"
            :options="{ group: { name: 'itxst', pull: false }, sort: false }" @add="onAdd">
            <transition-group class="group" :style="style">
              <div class="item" v-for="(item, index) in arr2" :key="item.id">
                <div class="right-item" :class="{ 'active': selectedIndex === index, 'item': true }"
                  @mouseenter="handleMouseEnter(item)" @mouseleave="handleMouseLeave(item)"
                  @click="rightClick(index, item)">
                  <label>{{ item.name }}</label>
                  <div class="item-body">
                    <span>{{ item.desc }}</span>
                    <a-icon :type="item.icon2" />
                    <a-icon type="close" class="icon-pos" v-show="item.show" @click="handleClick(item, 'right')" />
                  </div>
                </div>
              </div>
            </transition-group>
          </draggable>
        </div>
      </div>
      <div>
        <el-drawer :title="title" :visible.sync="drawer" direction="rtl" :before-close="handleClose" size="500"
          close-on-press-escape>
          <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
            <el-form-item label="字段名称" prop="name">
              <el-input v-model="ruleForm.name" @input="handleNameInput"></el-input>
            </el-form-item>
            <el-form-item label="提示文字" prop="placeholder">
              <el-input v-model="ruleForm.placeholder" @input="handlePlaceholderInput"></el-input>
            </el-form-item>
            <el-form-item label="选项" v-if="addType == 'select'" prop="opt">
              <div v-for="(i, index) in ruleForm.opt" :key="index" style="margin: 5px 0;">
                <el-row>
                  <el-col :span="20">
                    <el-input v-model="i.label"></el-input>
                  </el-col>
                  <el-col :span="4">
                    <i class="el-icon-remove-outline" style="margin:  5px ;font-size: 24px;"
                      @click.prevent="removeDomain(i)"></i>
                  </el-col>
                </el-row>
              </div>

              <el-button @click="addDomain">新增选项</el-button>
            </el-form-item>
            <el-form-item label="字符类型" prop="type" v-if="addType == 'text'">
              <el-radio-group v-model="ruleForm.type">
                <el-radio label="num">数字</el-radio>
                <el-radio label="any">不限制</el-radio>
              </el-radio-group>
            </el-form-item>
            <el-form-item label="字符长度" v-if="addType == 'text'">
              <el-form-item label="字符最长" prop="maxLength">
                <el-input-number v-model="ruleForm.maxLength" :min="1" @change="handleMaxChange"></el-input-number>
              </el-form-item>
              <br />
              <el-form-item label="字符最短" prop="minLength">
                <el-input-number v-model="ruleForm.minLength" :min="1" @change="handleMinChange"></el-input-number>
              </el-form-item>
            </el-form-item>
            <el-form-item label="设置列宽" prop="labelWidth">
              <el-input-number v-model="ruleForm.labelWidth" :min="1"></el-input-number>
            </el-form-item>
            <el-form-item label="日期类型" prop="date" v-if="addType == 'date'">
              <el-radio-group v-model="ruleForm.date">
                <el-radio label="month">年-月</el-radio>
                <el-radio label="day">年-月-日</el-radio>
                <el-radio label="time">年-月-日 时-分</el-radio>
              </el-radio-group>
            </el-form-item>
            <el-form-item label="是否必填" prop="isRequired">
              <el-radio-group v-model="ruleForm.isRequired">
                <el-radio label="y">必填</el-radio>
                <el-radio label="n">非必填</el-radio>
              </el-radio-group>
            </el-form-item>
            <el-form-item>
            </el-form-item>
          </el-form>
        </el-drawer>
      </div>
    </div>
    <a-button @click="handleCreate">创建</a-button>
    <a-button @click="handleClean">清除缓存</a-button>
    <el-dialog title="表单生成" :visible.sync="visibleModal" :before-close="handleClose">
      <el-form :model="endForm" :rules="endRules" ref="endForm" label-width="100px" class="demo-ruleForm">
        <el-form-item v-for="item in formData " :key="item.id" :label="item.name" :label-width="item.labelWidth"
          :prop="item.val" :rules="[
            { required: item.conf.isRequired == 'y' ? true : false, message: `${item.name}必填`, trigger: ['blur', 'change'] },
          ]">

          <el-select v-model="endForm.radio" :placeholder="item.desc" v-if="item.val == 'radio'">
            <el-option v-for="i in item.conf.opt" :key="i.value" :label="i.label" :value="i.value">
            </el-option>
          </el-select>
          <el-select v-model="endForm.checkbox" multiple :placeholder="item.desc" v-else-if="item.val == 'checkbox'">
            <el-option v-for="i in item.conf.opt" :key="i.value" :label="i.label" :value="i.value">
            </el-option>
          </el-select>
          <el-input v-model="endForm.text" v-else-if="item.val == 'text' && item.conf.type != 'num'"
            :minlength="item.conf.minLength" :maxlength="item.conf.maxLength">
          </el-input>
          <el-input-number v-model="endForm.text" :min="item.conf.minLength" :max="item.conf.maxLength"
            v-else-if="item.val == 'text' && item.conf.type == 'num'"></el-input-number>
          <el-input type="textarea" show-word-limit :minlength="item.conf.minLength" :maxlength="item.conf.maxLength"
            v-model="endForm.textarea" v-else-if="item.val == 'textarea'"></el-input>

          <el-date-picker v-model="endForm.date" type="datetime" :placeholder="item.desc" value-format="yyyy-MM-dd HH-mm"
            v-else-if="item.val == 'date' && item.conf.date == 'time'">
          </el-date-picker>
          <el-date-picker v-model="endForm.date" :type="item.conf.date == 'day' ? 'date' : 'month'" placeholder="选择日期"
            v-else-if="item.val == 'date' && item.conf.date != 'time'"></el-date-picker>
          <el-upload class="avatar-uploader" action="https://jsonplaceholder.typicode.com/posts/" :show-file-list="false"
            v-else-if="item.val == 'img'">
            <img v-if="imageUrl" :src="imageUrl" class="avatar">
            <i v-else class="el-icon-plus avatar-uploader-icon"></i>
          </el-upload>
          <el-upload class="upload-demo" action="https://jsonplaceholder.typicode.com/posts/" multiple :limit="3" v-else>
            <el-button size="small" type="primary">点击上传</el-button>
          </el-upload>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="visibleModal = false">取 消</el-button>
        <el-button type="primary" @click="handleOk">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
import draggable from 'vuedraggable';
export default {
  name: 'Draggable',
  props: {

  },
  components: {
    draggable
  },
  data() {
    return {
      arr1: [
        { id: 3, name: '单选下拉框', val: 'radio', icon: 'down-circle', icon2: 'right', desc: "请选择", show: false },
        { id: 4, name: '多选下拉框', val: 'checkbox', icon: 'down-square', icon2: 'right', desc: "请选择", show: false },
        { id: 5, name: '单行文本', val: 'text', icon: 'font-colors', icon2: 'right', desc: "请输入", show: false },
        { id: 6, name: '多行文本', val: 'textarea', icon: 'font-size', icon2: 'right', desc: "请输入", show: false },
        { id: 7, name: '选择档案', val: 'upload', icon: 'database', icon2: 'right', desc: "请输入", show: false },
        { id: 8, name: '图片', val: 'img', icon: 'file-image', icon2: 'right', desc: "请上传", show: false },
        { id: 9, name: '日期', val: 'date', icon: 'calendar', icon2: 'right', desc: "请选择", show: false },
        { id: 10, name: '关联档案', val: 'upload2', icon: 'file-text', icon2: 'right', desc: "请输入", show: false },
      ],
      arr2: [],
      style: {
        minHeight: '50vh',
        display: "block",
        backgroundColor: '#f3f3f3',
      },
      cache: {},
      temp: {},
      selectedIndex: null,
      drawer: false,
      visibleModal: false,
      title: null,
      addType: null,
      formData: [],
      imageUrl: [],
      ids: [],
      ruleForm: {
        name: null,
        placeholder: null,
        labelWidth: 200,
        isRequired: 'y',
        minLength: 1
      },
      rules: {
        name: [
          { required: true, message: '字段名称必填', trigger: ['change', 'blur'] }
        ],
        maxLength: [
          { required: true, message: '字符最长必填', trigger: ['change', 'blur'] }
        ],
        minLength: [
          { required: true, message: '字符最短必填', trigger: ['change', 'blur'] }
        ],
        labelWidth: [
          { required: true, message: '请设置列宽', trigger: ['change', 'blur'] }
        ],
      },
      endRules: {   },
      endForm: {
        checkbox: []
      }
    }
  },
  methods: {
    mouseEnter(e) {
      this.cache = e
    },
    handleMouseEnter(e) {
      (e.id != 1 && e.id != 2) ? e.show = true : e.show = false
    },
    handleMouseLeave(e) {
      e.show = false
    },
    handleClick(item, type) {
      if (type == 'right') {
        if (window.confirm("是否确认删除?")) {
          this.arr2.splice(this.arr2.indexOf(item), 1);
        }
      }
    },
    onMove(e) {
      this.cache = e.draggedContext.element
      return true;
    },
    generateUniqueId() {
      return Math.random().toString(36).substring(2)
    },
    onAdd(e) {
      const ori = { ...this.cache };
      const newItemId = this.generateUniqueId();
      Object.assign(ori, { id: newItemId });
      this.arr2.splice(e.newIndex, 1, ori);
    },
    addDomain() {
      this.ruleForm.opt.push({
        label: `选项${this.ruleForm.opt.length + 1}`,
        value: Date.now()
      });
    },
    removeDomain(item) {
      var index = this.ruleForm.opt.indexOf(item)
      if (index !== -1) {
        this.ruleForm.opt.splice(index, 1)
      }
    },
    handleClose() {
      this.$refs.ruleForm.validate((valid) => {
        if (valid) {
          this.temp.conf = this.ruleForm
          localStorage.setItem(this.temp.id, JSON.stringify(this.temp))
          this.ids.push(this.temp.id)
          this.drawer = false
        } else {
          this.$message.error('请填写完整信息')
          return false;
        }
      });
    },
    rightClick(e, item) {
      this.temp = item
      this.selectedIndex = e;
      this.title = item.name

      const ori = JSON.parse(localStorage.getItem(item.id))
      if (ori) {
        if (item.val == 'radio' || item.val == 'checkbox') {
          this.addType = "select"
          this.$set(this.ruleForm, 'opt', [
            { label: '选项1', value: Date.now() },
            { label: '选项2', value: Date.now() + 1 },
            { label: '选项3', value: Date.now() + 2 },
          ],)
        } else if (item.val == 'date') {
          this.addType = "date"
        } else if (item.val == 'text') {
          this.addType = "text"
        } else {
          this.addType = "text"
        }
        this.ruleForm = ori.conf
        this.drawer = true
        return
      }

      const arr = JSON.parse(localStorage.getItem('formData'))
      const tar = arr && arr.filter(i => i.id == item.id)
      if (tar && tar.length > 0) {
        if (item.val == 'radio' || item.val == 'checkbox') {
          this.addType = "select"
          this.$set(this.ruleForm, 'opt', [
            { label: '选项1', value: Date.now() },
            { label: '选项2', value: Date.now() + 1 },
            { label: '选项3', value: Date.now() + 2 },
          ],)
        } else if (item.val == 'date') {
          this.addType = "date"
          this.$set(this.ruleForm, 'date', 'month')
        } else if (item.val == 'text') {
          this.addType = "text"
          this.$set(this.ruleForm, 'type', "num")
          this.$set(this.ruleForm, 'minLength', 1)
        } else {
          this.addType = "text"
          this.$set(this.ruleForm, 'type', "any")
          this.$set(this.ruleForm, 'minLength', 1)
        }
        this.ruleForm = tar[0].conf
      } else {
        this.ruleForm = {
          labelWidth: 200,
          isRequired: 'y',
        }
        if (item.val == 'radio' || item.val == 'checkbox') {
          this.addType = "select"
          this.$set(this.ruleForm, 'opt', [
            { label: '选项1', value: Date.now() },
            { label: '选项2', value: Date.now() + 1 },
            { label: '选项3', value: Date.now() + 2 },
          ],)
        } else if (item.val == 'date') {
          this.addType = "date"
          this.$set(this.ruleForm, 'date', 'month')
        } else if (item.val == 'text') {
          this.addType = "text"
          this.$set(this.ruleForm, 'type', "num")
          this.$set(this.ruleForm, 'minLength', 1)
        } else {
          this.addType = "text"
          this.$set(this.ruleForm, 'type', "any")
          this.$set(this.ruleForm, 'minLength', 1)
        }
        this.$set(this.ruleForm, 'name', item.name)
        this.$set(this.ruleForm, 'placeholder', item.desc)

      }

      this.drawer = true

    },
    handleNameInput() {
      this.temp.name = this.ruleForm.name
    },
    handleMaxChange(value) {
      const min = this.ruleForm.minLength
      if (min > value) {
        this.$set(this.ruleForm, 'minLength', value)
      }
    },
    handleMinChange(value) {
      const max = this.ruleForm.maxLength
      if (max < value) {
        this.$set(this.ruleForm, 'maxLength', value)
      }
    },
    handlePlaceholderInput() {
      this.temp.desc = this.ruleForm.placeholder
    }, 

    handleOk() {
      this.$refs.endForm.validate((valid) => {
        if (valid) {
          console.log('表单值', this.endForm);
          console.log('配置值', JSON.parse(localStorage.getItem('formData')));
        } else {
          return false;
        }
      });
    },

    handleCreate() {
      if (this.arr2.length == 0) {
        this.$message.warning(`请先配置页面`)
        return
      }
      this.endForm = { checkbox: [] }
      localStorage.setItem('formData', JSON.stringify(this.arr2))
      this.visibleModal = true;
      this.formData = this.arr2
    },

    handleClean() {
      if (this.arr2.length > 0) {
        this.arr2 = this.arr2.map(i => {
          if (i.val == 'radio') {
            i.name = "单选下拉框"
            i.desc = "请选择"
          }
          if (i.val == 'checkbox') {
            i.name = "多选下拉框"
            i.desc = "请选择"
          }
          if (i.val == 'text') {
            i.name = "单行文本"
            i.desc = "请输入"
          }
          if (i.val == 'textarea') {
            i.name = "多行文本"
            i.desc = "请输入"
          }
          if (i.val == 'upload') {
            i.name = "选择档案"
            i.desc = "请输入"
          }
          if (i.val == 'img') {
            i.name = "图片"
            i.desc = "请上传"
          }
          if (i.val == 'date') {
            i.name = "日期"
            i.desc = "请选择"
          }
          if (i.val == 'upload2') {
            i.name = "关联档案"
            i.desc = "请输入"
          }
          return i
        })
      }
      if (this.ids.length > 0) {
        this.ids.forEach(i => {
          localStorage.removeItem(i)
        });
      }
      this.ids = []
      localStorage.removeItem('formData')
    },
  },
}
</script>
<style scoped>
.wrapper {
  display: flex;

}

.center {
  position: relative;
  width: 40vw;
}

.left {
  width: 20vw;
  height: 90vh;
  background-color: #fff;
  margin: 10px;
  padding: 10px;
  border-radius: 5px;
}

.right {
  width: 300px;
  /* width: 15vw; */
  height: 60vh;
  border-radius: 30px;
  background-color: #fff;
  position: absolute;
  right: 20px;
  top: 20px;
}

.group {
  border-color: #66b1ff;
}

.left-group {
  border-color: #66b1ff;
  display: flex;
  width: 20vw;
  flex-wrap: wrap;

}

.flex-item {
  flex: 0 0 50%;
  box-sizing: border-box;
  padding: 10px;

}

.flex-item-item {
  border: 1px solid;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 5px;
  border-radius: 3px;
  width: 8vw;
  cursor: move;
}

.right-item {
  border: 1px solid #eee;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px;
  width: 100%;
  background: #fff;
  margin: 10px 0;
}

.right-item:hover {
  border: 1px dotted #14ce90;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px;
  width: 100%;
  background: #fff;
  margin: 10px 0;
}

.item-body {
  position: relative;
}

.icon-pos {
  position: absolute;
  top: -10px;
}

.move {
  cursor: move;
}

.active {
  border: 1px solid #14ce90 !important;
}
</style>
 